﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net.NetworkInformation;
using Microsoft.Practices.Composite.Modularity;
using Microsoft.Practices.Composite.Presentation.Commands;
using Microsoft.Practices.Composite.Regions;
using Microsoft.Practices.Unity;
using TelecoSystems.Infrastructure;
using TelecoSystems.Infrastructure.Views;
using TelecoSystems.Views.Profile;

namespace TelecoSystems.ViewModels {
    public class ShellViewModel : INotifyPropertyChanged {
        #region Fields
        IModuleManager moduleManager;
        IRegionManager regionManager;
        IUnityContainer unityContainer;
        #endregion

        #region Constructors
        public ShellViewModel(IModuleManager _moduleManager, IRegionManager _regionManager, IUnityContainer _unityContainer) {
            moduleManager = _moduleManager;
            regionManager = _regionManager;
            unityContainer = _unityContainer;

            ActivateModuleCommand = new DelegateCommand<string>(ActivateModule, CanActivateModule);
            InstallCommand = new DelegateCommand<object>(Install, CanInstall);
            ShowProfileCommand = new DelegateCommand<object>(ShowProfile, (o) => true);

            NetworkChange.NetworkAddressChanged += (s, e) => {
                NotifyPropertyChanged("OnlineStatus");
            };

            IsBusy = false;
        }
        #endregion

        #region VM Properties
        public static IModuleCatalog ModuleCatalog { get; set; }

        public IEnumerable<ModuleInfo> Modules {
            get {
                //toto: retrieve from somewhere list of allowed modules for logged user
                List<string> allowedModules = GetUserAuthorizedModules();

                var q = from m in ModuleCatalog.Modules
                        join am in allowedModules on m.ModuleName equals am
                        select m;

                return q.ToList();
            }
        }

        private static List<string> GetUserAuthorizedModules() {
            List<string> allowedModules = new List<string>();
            if (WebContext.Current.User.IsInRole("Administrator")) {
                allowedModules.Add("Dashboard");
                allowedModules.Add("Administration");
            }
            if(WebContext.Current.User.IsInRole("Manager")) {
                allowedModules.Add("Dashboard");
                allowedModules.Add("Products");                
            }
            if(WebContext.Current.User.IsInRole("Dealer")) {
                allowedModules.Add("Dashboard");
                allowedModules.Add("Customers");
                allowedModules.Add("Contracts");                
            }
            return allowedModules;
        }

        public const string PathToModuleIcon = "/TelecoSystems.Modules.{0};component/Assets/Icons/{0}.png";

        private bool isBusy;
        public bool IsBusy {
            get { return isBusy; }
            set { isBusy = value; NotifyPropertyChanged("IsBusy"); }
        }

        public bool IsInstalled {
            get { return App.Current.InstallState == System.Windows.InstallState.Installed; }
            set {
                IsInstalled = value;
                NotifyPropertyChanged("IsNotInstalled");
                if (InstallCommand != null) InstallCommand.RaiseCanExecuteChanged();
            }
        }

        public bool IsNotInstalled { get { return !IsInstalled; } }

        public string ModeStatus {
            get {
                return "Mode: " + (App.Current.IsRunningOutOfBrowser ? "Out of Browser" : "Web");
            }
        }

        public string OnlineStatus {
            get {
                return "Network: " + (NetworkInterface.GetIsNetworkAvailable() ? "Online" : "Offline");
            }
        }

        public string BusyContent {
            get { return "Module is loading, please wait..."; }
        }
        #endregion

        #region Commands
        public DelegateCommand<string> ActivateModuleCommand { get; set; }
        protected void ActivateModule(string moduleName) {
            IsBusy = true;

            moduleManager.LoadModule(moduleName);

            var view = regionManager.Regions[RegionNames.MainRegion].GetView(moduleName + "ModuleView");
            if (view != null) {
                regionManager.Regions[RegionNames.MainRegion].Activate(view);
            }

            IsBusy = false;
        }
        protected bool CanActivateModule(string s) {
            return true;
        }

        public DelegateCommand<object> InstallCommand { get; set; }
        protected void Install(object o) {
            App.Current.Install();
            App.Current.InstallStateChanged += new System.EventHandler(Current_InstallStateChanged);
        }
        protected bool CanInstall(object o) {
            return IsNotInstalled;
        }

        public DelegateCommand<object> ShowProfileCommand { get; set; }
        public void ShowProfile(object o) {
            UserProfileView profileView = unityContainer.Resolve<UserProfileView>();
            profileView.Show();
        }
        #endregion

        #region Event Handlers
        protected void Current_InstallStateChanged(object sender, EventArgs e) {
            if (IsInstalled) {
                InformationWindow.Create("Application was successfully installed.\nYou can now close this window.", "Installation successful");
            } else if (App.Current.InstallState == System.Windows.InstallState.InstallFailed) {
                ErrorWindow.CreateNew("Application couldn't be installed on your machine. Try again later.");
            }
            InstallCommand.RaiseCanExecuteChanged();
        }
        #endregion

        #region INotifyPropertyChanged Members
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(string propertyName) {
            if (PropertyChanged != null) {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion
    }
}
